﻿#ifndef _CELLCLIENT_H_
#define _CELLCLIENT_H_

#include "CELL.h"
#include "CELLObjectPool.hpp"
#include "CELLNetWork.hpp"
#include <vector>
#include "CELLBuffer.hpp"

// 客户端心跳检测死亡计时时间 10秒钟（单位：毫秒）
#define CLIENT_HEART_DEAD_TIME 10000
// 指定时间内清空发送缓冲区(清空指发送)
#define CLIENT_SEND_BUF_TIME 200

// 每个客户端的缓冲区控制根据业务需求的差异而调整

// 每次加入一个客户端都会创建一个CELLClient对象，这个对象池归对象池管理
class CELLClient : public ObjectPoolBase<CELLClient, 1024>
{
public:
	CELLClient(SOCKET sock = INVALID_SOCKET, int sendSize = SEND_BUF_SIZE, int recvSize = RECV_BUF_SIZE)
		: _sockfd(sock), _sendBuff(sendSize), _recvBuff(recvSize)
	{
		static int n = 1;
		id = n++;
		// 初始化客户端的时候死亡倒计时清0
		resetDtHeart();
		// 初始化客户端上次发送消息时间
		resetDtSend();
	}

	~CELLClient()
	{
		CELLLog_Debug("CELLClient %d ~CELLClient", id);
		destory();
	}

	void destory()
	{
		// 将socket关闭
		if (_sockfd != INVALID_SOCKET)
		{
			CELLLog_Debug("CELLClient %d destory", id);
			CELLNetWork::destorySocket(_sockfd);
			_sockfd = INVALID_SOCKET;
		}
	}

	// 获得本客户端套接字
	SOCKET sockfd()
	{
		return _sockfd;
	}

	// 发回数据
	int SendData(DataHeader* header)
	{
		return SendData((const char*)header, header->dataLength);
	}

	int SendData(const char* pData, int len)
	{
		if (_sendBuff.push(pData, len))
		{
			return len;
		}
		return SOCKET_ERROR;
	}

	// 立即发送发送缓冲区的数据
	int SendDataReal()
	{
		resetDtSend();
		return _sendBuff.write2socket(_sockfd);
	}

	// 接收数据
	int RecvData()
	{
		return _recvBuff.read4socket(_sockfd);
	}

	// 接收有无消息
	bool hasMsg()
	{
		return _recvBuff.hasMsg();
	}

	// 发送缓冲区是否有数据需要发送
	bool needWrite()
	{
		return _sendBuff.needWrite();
	}

	// 得到第一条消息
	DataHeader* front_msg()
	{
		return (DataHeader*)_recvBuff.data();
	}

	// 删除最前面一条消息
	void pop_front_msg()
	{
		if (hasMsg())
			_recvBuff.pop(front_msg()->dataLength);
	}

	// 把心跳计时置0
	void resetDtHeart()
	{
		_dtHeart = 0;
	}

	// 重置上次发送时间_dtSend
	void resetDtSend()
	{
		_dtSend = 0;
	}

	// 心跳检测
	bool checkHeart(time_t dt)
	{
		_dtHeart += dt;
		if (_dtHeart >= CLIENT_HEART_DEAD_TIME)
		{
			CELLLog_Info("chackHeart dead: %d, time: %d", _sockfd, _dtHeart);
			return true;
		}
		return false;
	}

	// 定时发送消息检测
	bool checkSend(time_t dt)
	{
		_dtSend += dt;
		if (_dtSend >= CLIENT_SEND_BUF_TIME)
		{
			// CELLLog_Info("超时发送");
			// 立即将缓冲区数据发送出去
			SendDataReal();
			// 重置上次发送数据时间(上一行函数里也重置了，防止其它函数调用它时没有重置)
			resetDtSend();
		}
		return false;
	}

	// 以下几个为用于调试的成员变量
	// 测试所用id
	int id;
	// 累计发送消息
	int _nSendMsgCount = 1;
	// 累计接收消息
	int _nRecvMsgCount = 1;
#ifdef CELL_USE_IOCP // 如果使用了IOCP模式
	IO_DATA_BASE* makeRecvIOData()
	{
		if (_isPostRecv)
			return nullptr;
		_isPostRecv = true;
		return _recvBuff.makeRecvIOData(_sockfd);
	}

	// 告知缓冲区本次接收到数据的长度
	void recv4Iocp(int nRecv)
	{
		if (!_isPostRecv)
			CELLLog_Error("CELLClient recv4Iocp, _isPostRecv=false");
		_isPostRecv = false;
		_recvBuff.read4iocp(nRecv);
	}

	IO_DATA_BASE* makeSendIOData()
	{
		if (_isPostSend)
			return nullptr;
		_isPostSend = true;
		return _sendBuff.makeSendIOData(_sockfd);
	}

	void send2Iocp(int nSend)
	{
		if (!_isPostSend)
			CELLLog_Error("CELLClient send2Iocp, _isPostSend=false");
		_isPostSend = false;
		_sendBuff.write2iocp(nSend);
	}

	bool isPostIoAction()
	{
		return _isPostRecv || _isPostSend;
	}
#endif // #ifdef CELL_USE_IOCP

private:
	// 上次发送消息数据的时间
	time_t _dtSend;
	// 当前客户端套接字
	SOCKET _sockfd;
	// 接收消息缓冲区
	CELLBuffer _recvBuff;
	// 发送缓冲区
	CELLBuffer _sendBuff;
	// 心跳死亡计时
	time_t _dtHeart;
#ifdef CELL_USE_IOCP // 如果使用了IOCP模式
	bool _isPostRecv = false;
	bool _isPostSend = false;
#endif
};

#endif // #ifndef _CELLCLIENT_H_
